
from emmodels.em_rollback import Rollback
from emmodels.em_position2 import Assets
from sysdata import sys_base_data as sysBaseData
from emutils import time_utils
from dateutil.parser import parse
from emfundindicator import sfund_lib
from LSTM.variableset import EMVar, EMPath
import pandas as pd
import numpy as np
from emsina.stock import info
from em_logger import logger as logger

def caculate_cixin_shizi():
    from emtencent import em_classified
    import datetime
    cixin_stks = em_classified.get_tc_concept_code_df(concept_id='021023')
    datas = []
    cout = 0
    for index, item in cixin_stks.iterrows():
        try:
            cout += 1
            sfund = sysBaseData.get_self_fund(item['code'])
            data = caculate_stk_shizi(sfund.stkcode)
            datas.append(data)
            # if cout == 50:
            #     break
        except Exception as e:
            print('%s 获取 异常，原因→→→→' % sfund.code_with_name())
            print(e)
            continue
    total_df = pd.concat(datas, ignore_index=True)
    total_df.to_csv(path_or_buf=EMPath.data_file_full_path(is_common=True, fileName='result_cixin.csv'), index=False)
    pass


def caculate_stk_shizi(stkcode):

    sfund = sysBaseData.get_self_fund(stkcode=stkcode)
    # sfund = sysBaseData.get_self_fund('600792')
    df = info.get_profit(stkcode, sleep_sec=5)
    if not df.empty:
        logger.info('%s 有除权除息数据，不纳入计算'%sfund.code_with_name())
        raise Exception('%s 有除权除息数据，不纳入计算'%sfund.code_with_name())

    sfund.update_from_ts()
    if sfund.now < 12:
        raise Exception('当前价格小于12，不符合要求')
    day_data = sfund.get_index(start='2017-01-01', ktype='D', insertdb=False)
    data = sfund.get_index(start='2011-01-01', ktype='60', append_now=True, indicator='shape', insertdb=False)

    aH2L = data[EMVar.ABS_HIGH2LOW] < 0.006
    aC2O = data[EMVar.ABS_CLOSE2OPEN] < 0.002

    # day_data = day_data[EMVar.dm1_ajx_price, EMVar.date]
    # tmp_filter[EMVar.date].apply(lambda x: x[0:10])
    tmp_filter = data[aH2L & aC2O]
    result = []

    # pd.merge(tmp_filter, day_data, on=EMVar.date)

    if tmp_filter.shape[0]:
        for name, item in tmp_filter.iterrows():
            shizi_day = name.strftime(EMVar.FORMATE_YMD)
            shizi_price = item[EMVar.close]
            if shizi_day in day_data.index:
                ajx_price = day_data.ix[shizi_day][EMVar.dm1_ajx_price]
                shizi_day_close = day_data.ix[shizi_day][EMVar.close]
                # if ajx_price >= 0.09 or np.isnan(ajx_price):
                if np.isnan(ajx_price):
                    print('ajx_price nan')
                else:
                    if (shizi_day_close == shizi_price and (ajx_price >= 0.09 or ajx_price <= -0.09)) :
                        print('%s 十字星%s 停板 ,涨跌幅为 %3.2f，模型不匹配' % (sfund.code_with_name(), shizi_day, ajx_price))
                    elif (np.abs((shizi_day_close-shizi_price)/shizi_price)>0.09):
                        print('%s 数据异常,价格相差超过10%%'% sfund.code_with_name())
                    else:
                        result.append(dict(item))
    return pd.DataFrame(result)

class Rollback1(Rollback):

    def load_stks(self):
        self.assets = Assets(init_assets=50000, strategy_name='CIXIN_SHIZI_T4')
        # self.assets.recover_from_db()
        self.assets = self.assets
        self.total_datas = pd.read_csv(filepath_or_buffer=EMPath.data_file_full_path(is_common=True, fileName='result_cixin.csv'))
        self.total_datas[EMVar.date] = pd.to_datetime(self.total_datas[EMVar.date], errors='coerce')
        self.total_datas[EMVar.code] = self.total_datas[EMVar.code].astype(str)
        self.total_datas = self.total_datas.set_index([EMVar.date], drop=False)

    def before_open(self, date):
        if isinstance(self.total_datas, pd.DataFrame):
            if date in self.total_datas.index:
                stks = self.total_datas[date][EMVar.code]
                self.registe_stks = list(stks) + self.assets.get_all_own_stocks()
            pass
        pass

    def after_close(self, date):

        pass

    def __load_strategy_stks(self, date):
        pre_offset = self.params['pre_offset'] or 5
        return self.util_load_strategy_stks(date=date, pre_offset=pre_offset)

    def deliever(self, date_time, bar_datas):

        stop_loss = -0.05
        stop_win = 0.8
        is_reback = True
        high_profit_reback = 0.02
        max_reback = 0.10
        max_keep_days = 5
        cur_date = time_utils.reformater(date_time, EMVar.FORMATE_YMD)
        cur_time = parse(date_time)
        cur_date_pend_buy = self.total_datas[cur_date]

        try:
            for index, item in bar_datas.iterrows():
                item = dict(item)
                code = item[EMVar.code]
                bar_close_price = float(item[EMVar.close])
                sfund = sysBaseData.get_self_fund(code)
                if self.assets.couldsaile(date_time, code):
                    self.common_saile(self.assets,
                                      code,
                                      sfund.stkname,
                                      bar_close_price,
                                      date_time,
                                      stop_loss=stop_loss,
                                      stop_win=stop_win,
                                      is_reback=is_reback,
                                      max_reback=max_reback,
                                      max_keep_days=max_keep_days,
                                      high_profit_reback=high_profit_reback,
                                      callback=None)
                cur_time_pend_buy = cur_date_pend_buy[cur_date_pend_buy[EMVar.date] >= date_time]
                cur_code_time_pend_buy = cur_time_pend_buy[cur_time_pend_buy[EMVar.code] == code]
                if not cur_code_time_pend_buy.empty:
                    cur_time_pend_buy.sort_values([EMVar.date], inplace=True)
                    last_item = cur_code_time_pend_buy.ix[0]
                    if bar_close_price >= last_item[EMVar.close] and cur_time>= last_item[EMVar.date]:
                        if self.assets.could_buy(date_time, code, bar_close_price):
                            self.assets.buy_stk(date_time=date_time, stkcode=code, name=sfund.stkname,
                                                price=bar_close_price,
                                                buy_total_money=15000,
                                                reason='十字星买入')


        except Exception as e:
            print(e)


# caculate_cixin_shizi()
rollback = Rollback1()
rollback.load_stks()
rollback.begin()